/* Universidade Federal de Campina Grande - UFCG
 * Centro de Engenharia Elétrica e Informática - CEEI
 * Departamento de Sistemas e Computação - DSC
 * Curso: Ciência da Computação
 * Disciplina: Desenvolvimento de Aplicações Corporativas Avançadas (2008.1)
 * Professor: Jacques Philippe Sauvé
 * Monitor: Guilherme Mauro Germoglio Barbosa
 * Alunos: Daniel Souza Coelho
 *                 Everton Leandro Galdino Alves
 *                 Odilon Francisco de Lima Junior      
 */

package lembrete.core.dao;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;

import lembrete.core.beans.Entrada;
import lembrete.core.beans.Usuario;
import lembrete.core.exceptions.ExcecaoBD;
import lembrete.core.exceptions.ExcecaoParametroInvalido;

import com.sun.mail.handlers.text_html;
import com.thoughtworks.xstream.XStream;
/**
 * Essa classe eh responsavel por salvar 
 * as informacoes dos usuarios do sistema em arquivos XML.
 *  
 * @author Everton Leandro <br>
 *         Odilon Francisco <br>
 *         Daniel Coelho <br>
 * @version 1.0 
 */
public class XMLUsuarioDao implements UsuarioDao {

	private static XMLUsuarioDao inst = null;
	private XStream xstream;
	private HashMap<String, Usuario> mapUsuarios;
	private String USER_FILE = "Usuarios.xml";
	private String PARAM_PATH = "";

	/**
	 * Metodo criador da classe.
	 */
	private XMLUsuarioDao(){
		xstream = new XStream();
		xstream.setMode(XStream.NO_REFERENCES);
		carregaDados();
	}

	/**
	 * Metodo que retorna uma instancia da classe. 
	 * 
	 * @return instancia da classe XMLUsuarioDao
	 */
	public static XMLUsuarioDao getInstancia(){
		if (inst == null) {
			inst = new XMLUsuarioDao();
		}
		return inst;
	}

	/**
	 * Este metodo pega os dados que estao salvos no
	 * BD(neste caso, nos arquvos) e carrega no sistema. 
	 * 
	 */
	private void carregaDados(){
		File arq = new File(PARAM_PATH + File.separator + USER_FILE);

		if (!arq.exists()) {
			mapUsuarios = new HashMap<String, Usuario>();
		}else{
			try {
				mapUsuarios = (HashMap<String, Usuario>) xstream.fromXML(new FileInputStream(PARAM_PATH + File.separator + USER_FILE));
			} catch (Exception e) {
				mapUsuarios = new HashMap<String, Usuario>();
			}
		}
	}

	/**
	 * Apaga os valores armazenados no BD.
	 * 
	 * @throws ExcecaoBD
	 * @throws FileNotFoundException
	 */
	public void limpaBD() throws ExcecaoBD, FileNotFoundException {
		mapUsuarios.clear();
		updateXML();
	}

	/**
	 * Atualiza o BD.
	 * 
	 * @param nomeBD
	 */
	public void setBD(String nomeBD) throws ExcecaoBD, FileNotFoundException {
		PARAM_PATH = CAMINHO_BD + File.separator + nomeBD;
		if (nomeBD != null && nomeBD.length() > 0) {
			//USER_PATH = PARAM_PATH + File.separator + USER_FILE;
			File dir = new File(PARAM_PATH);
			if(!dir.isDirectory()){
				if(!dir.mkdir()){
					throw new ExcecaoBD("Erro ao criar diretorio");
				}    			   
			}
			carregaDados();
			updateXML();
		}          
	}

	/**
	 * Procura um usuario com o email dado.
	 * 
	 * @param email
	 * @return Usuario procurado
	 */
	public Usuario procuraUsuario(String email) throws ExcecaoBD {
		Usuario us = mapUsuarios.get(email);
		if (us == null) {
			throw new ExcecaoBD("Usuario nao cadastrado.");
		}
		return us;
	}

	/**
	 * Atualiza os valores no arquivo XML.
	 * 
	 * @throws FileNotFoundException
	 * @throws ExcecaoBD
	 */
	private void updateXML() throws FileNotFoundException, ExcecaoBD{
		try {
			xstream.toXML(mapUsuarios, new FileOutputStream(PARAM_PATH + File.separator + USER_FILE));
		} catch (Exception e) {
			//e.printStackTrace();
			throw new ExcecaoBD("Erro ao Salvar Dados"); 
		}    	  
	}

	/**
	 * Adiciona um usuario na base de dados do sistema.
	 * @param Usuario
	 */
	public void adicionaUsuario(Usuario usuario) throws ExcecaoBD, FileNotFoundException {
		mapUsuarios.put(usuario.getEmail(), usuario);
		updateXML();			
	}

	/**
	 * Adiciona entrada na agenda. 
	 * 
	 * @param email
	 * @param nome
	 * @param telefone
	 * @param aniversario
	 * @param idEnt
	 * @throws FileNotFoundException
	 * @throws ExcecaoBD
	 */
	public void adicionaEntrada(String email,String nome, String telefone,
			String aniversario, Long idEnt) throws ExcecaoBD, FileNotFoundException {

		Usuario us = procuraUsuario(email);
		us.insereEntrada(nome,telefone,aniversario, idEnt);
		updateXML();
	}

	/**
	 * Procura um determinado  atributo de um contato na agenda do usuario.
	 * 
	 * @param email
	 * @param idContato
	 * @param nomeAtrib
	 */
	public String buscaContato(String email, String idContato, String nomeAtrib) throws ExcecaoBD, ExcecaoParametroInvalido {
		Usuario us = procuraUsuario(email);
		return us.procuraContato(idContato, nomeAtrib);

	}

	/**
	 * Retorna uma entrada como string
	 * 
	 * @param idEntrada
	 * @return
	 * @throws ExcecaoBD
	 */
	public String visualizarEntrada(String emailUsuario, String idEntrada) throws ExcecaoBD {
		Usuario us = procuraUsuario(emailUsuario);
		return us.visualizarEntrada(idEntrada);
	}

	/**
	 * Edita uma entrada da agenda, baseando-se no id dessa entrada.
	 *  
	 * 
	 * @param idEntrada
	 * @param campoAntigo
	 * @param novoCampo
	 * @throws ExcecaoParametroInvalido 
	 * @throws ExcecaoBD                
	 */
	public void editarEntrada(String emailUsuario, String idEntrada, 
			String campoAntigo,String novoCampo) throws ExcecaoBD, ExcecaoParametroInvalido, FileNotFoundException{
		Usuario us = procuraUsuario(emailUsuario);
		us.editarEntrada(idEntrada,campoAntigo,novoCampo);
		updateXML();
	}

	/**
	 * Passa o id do grupo para o usuario.
	 * 	 
	 *  @param idGrupo
	 * @throws FileNotFoundException 
	 */
	public void conectaUsuarioGrupo(Long idGrupo, String usuarioEmail) throws ExcecaoBD, FileNotFoundException {
		procuraUsuario(usuarioEmail).conectaAoGrupo(idGrupo);
		updateXML();

	}

	/**
	 * Retorna o valor de uma entrada, baseando-se em seu id.
	 * 
	 * @param entradaId
	 * @return Entrada
	 * @throws ExcecaoBD
	 */
	public Entrada getEntrada(String idUsuario, String entradaId) throws ExcecaoBD {
		return procuraUsuario(idUsuario).getEntrada(entradaId);

	}

	/**
	 * Salva as modificacoes feitas na base de dados.
	 */
	public void salvaModificacoes() throws FileNotFoundException, ExcecaoBD {
		updateXML();

	}

	/**
	 * Exclui uma entrada da agenda
	 * 
	 * @param emailUsuario
	 * @param idGrupo
	 * @param idEntrada
	 */
	public void excluirEntrada(String emailUsuario, String idGrupo,
			String idEntrada) throws ExcecaoBD, FileNotFoundException {
		Usuario usuario = procuraUsuario(emailUsuario);
		usuario.excluirEntrada(idEntrada);
		updateXML();

	}

	/**
	 * Obtem usuario a partir de uma entrada.
	 * 
	 * @param idEntrada
	 * @return Usuario
	 */
	public Usuario getUsuarioPorEntrada(String idEntrada) throws ExcecaoBD {
		for (String string : mapUsuarios.keySet()){
			Usuario u = mapUsuarios.get(string);
			try {
				u.getEntrada(idEntrada);
				return u;
			} catch (Exception e) {

			}
		}
		return null;
	}

	public void excluiEntrada(String idEntrada) throws ExcecaoBD, FileNotFoundException {
		Usuario us = getUsuarioPorEntrada(idEntrada);
		us.excluirEntrada(idEntrada);
		updateXML();
	}

	public ArrayList<Usuario> getusuarios() {
		ArrayList<Usuario> array = new ArrayList<Usuario>(); 
		for (String email: mapUsuarios.keySet())
			array.add(mapUsuarios.get(email));
		
		return array;
	}

	public void removeMsg(String email, String descricao) throws FileNotFoundException, ExcecaoBD {
		Usuario u = procuraUsuario(email);
		u.removeMsg(descricao);
		updateXML();
	}

//	/**
//	 * Adiciona entrada.
//	 */
//	public Long adicionaEntrada(String email, String nome, String telefone,
//			String aniversario) throws ExcecaoBD, FileNotFoundException {
//		// TODO Auto-generated method stub
//		return null;
//	}


}


